﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CheckersBoardEngine;
using System.IO;
using GameEngine;


namespace EngineAdmin
{
    /// <summary>
    /// Checkers Board Engine Facade
    /// </summary>
    public class CBEngineFacade : EngineFacadeBase
    {
        /// <summary>
        /// Class representing CLI wrapper object of Checkers Board engine
        /// </summary>
        private CBEngine _engine = null;

        /// <summary>
        /// Path to the engine in the file system
        /// </summary>
        private string _enginePath;


        public CBEngineFacade(string enginePath)
        {
            _enginePath = enginePath;
        }

        /// <summary>
        /// Returns whether is loaded
        /// </summary>
        public bool IsLoaded
        {
            get
            {
                return _engine != null;
            }
        }

        public string ErrorMessage
        { get; set; }

        public string EnginePath
        {
            get
            {
                return _enginePath;
            }
        }


        /// <summary>
        /// Loads the CheckersBoard engine
        /// </summary>
        public bool LoadEngine()
        {
            try
            {
                if (File.Exists(_enginePath) == false)
                    throw new ApplicationException("Engine not found.");

                _engine = new CBEngine(_enginePath);

                return true;
            }
            catch (Exception ex)
            {
                ErrorMessage = ex.Message;

                _engine = null;
                return false;
            }
        }

        /// <summary>
        /// Frees the CB engine
        /// </summary>
        public void UnloadEngine()
        {
            try
            {
                _engine.Terminate();
                _engine = null;
            }
            catch
            {
                _engine = null;
            }
        }

        /// <summary>
        /// Retrieves the CB engine name
        /// </summary>
        public string GetEngineName()
        {
            try
            {
                // check loaded
                bool unload = false;
                if (IsLoaded == false)
                {
                    LoadEngine();
                    unload = true;
                }

                // retrieving the engine name
                string engineName = _engine.GetEngineName();

                // unload if necessary
                if (unload)
                {
                    UnloadEngine();
                }

                return engineName;
            }
            catch
            {
                return string.Empty;
            }                  
        }

        /// <summary>
        /// Retrives the draughts type
        /// </summary>
        public enumGameType? GetDraughtsType()
        {
            try
            {
                // check loaded
                bool unload = false;
                if (IsLoaded == false)
                {
                    LoadEngine();
                    unload = true;
                }

                // retrieving the engine name
                int draughtsCode = _engine.GetCheckersType();

                // unload if necessary
                if (unload)
                {
                    UnloadEngine();
                }

                return ConvertCodeToType(draughtsCode);
            }
            catch(Exception ex)
            {
                ErrorMessage = ex.Message;
                return null;                
            }
        }

        
        /// <summary>
        /// Returns the CB Engine options
        /// </summary>
        public void GetEngineOptions(out EngineOptions options, out EngineMoreOptions moreOptions)
        {
            if (!IsLoaded)
                throw new ApplicationException("Engine not loaded.");

            _engine.GetEngineOptions(out options, out moreOptions);
        }

        /// <summary>
        /// Sets the engine options
        /// </summary>
        public void SetEngineOptions(EngineOptions options, EngineMoreOptions moreOptions)
        {
            if (!IsLoaded)
                throw new ApplicationException("Engine not loaded.");

            _engine.SetEngineOptions(options, moreOptions);
        }

        /// <summary>
        /// Returns the state of CB Engine
        /// </summary>
        public CBEngineSettings GetSettingsForSave()
        {
            CBEngineSettings settings = new CBEngineSettings();
            settings.EnginePath = _enginePath;
            settings.IsLoaded = IsLoaded;
            return settings;
        }

          
        /// <summary>
        /// Computes the move
        /// </summary>
        public override void ComputeMove(GameStateConfig gameState)
        {
            throw new NotImplementedException();
        }


        /// <summary>
        /// Method converting the code to the checkers type
        /// </summary>
        private enumGameType ConvertCodeToType(int code)
        {
            switch (code)
            {
                
                case 20:	// 10x10 International draughts	
                    return enumGameType.International;
                case 21:	// English draughts	
                    return enumGameType.English;
                case 22:	// Italian draughts	
                    return enumGameType.Italian;
                case 23:	// American pool checkers	
                    throw new NotImplementedException();
                case 24:	// Spanish draughts	
                    return enumGameType.Spanish;
                case 25:	// Russian draughts	
                    return enumGameType.Russian;
                case 26:	// Brazilian draughts	
                    throw new NotImplementedException();
                case 27:	// Canadian draughts	
                    throw new NotImplementedException();
                case 28:	// Portuguese draughts	
                    throw new NotImplementedException();
                case 29:	// Czech draughts	
                    return enumGameType.Czech;
                case 30:	// Turkish draughts	
                    throw new NotImplementedException();
                case 31:	// Thai draughts	
                    throw new NotImplementedException();
                case 40:	// Frisian draughts	
                    throw new NotImplementedException();
                case 41:	// Spantsiretti draughts	
                    throw new NotImplementedException();
                default:
                    throw new ApplicationException("Unknown Draugts Code");
            }
        }

        public override int GetOpeningMoveCount()
        {
            throw new NotImplementedException();
        }

        public override List<BoardPos[]> GetOpeningByIndex(int index, GameStateConfig config)
        {
            throw new NotImplementedException();
        }
    }
}
